package de.windeln.marketing.campaign;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import de.windeln.marketing.campaign.services.ClientValidator;
import de.windeln.marketing.campaign.services.interfaces.CampaignService;
import de.windeln.marketing.campaign.costinterval.CostIntervalValueGenerator;
import de.windeln.marketing.campaign.costinterval.dailyCost.services.interfaces.DailyCostService;
import de.windeln.marketing.campaign.costinterval.model.CostintervalClientObject;
import de.windeln.marketing.campaign.costinterval.services.interfaces.CostIntervalService;
import de.windeln.marketing.campaign.model.RequestClientObject;
import de.windeln.marketing.utils.RandomNumberGenerator;
import de.windeln.marketing.validation.AlreadyExistingCampaign;
import de.windeln.marketing.validation.AnalyticsLinkGenerationError;
import de.windeln.marketing.validation.CampaignIntervalRoundCostInterval;
import de.windeln.marketing.validation.CampaignStartAfterEnd;
import de.windeln.marketing.validation.CostInformationOnlyByGivenDates;
import de.windeln.marketing.validation.CostIntervalStartAfterEnd;
import de.windeln.marketing.validation.VariableInformationByGivenNumberOfVariable;

@Controller
public class CampaignController {

	@Resource(name = "campaignService")
	private CampaignService campaignService;
	@Resource(name = "costIntervalService")
	private CostIntervalService costIntervalService;
	@Resource(name = "dailyCostService")
	private DailyCostService dailyCostService;
	@Resource(name = "alreadyExistingCampaign")
	private AlreadyExistingCampaign alreadyExistingCampaign;
	@Resource(name = "analyticsLinkGenerationError")
	private AnalyticsLinkGenerationError analyticsLinkGenerationError;
	@Resource(name = "campaignStartAfterEnd")
	private CampaignStartAfterEnd campaignStartAfterEnd;
	@Resource(name = "costInformationOnlyByGivenDates")
	private CostInformationOnlyByGivenDates costInformationOnlyByGivenDates;
	@Resource(name = "variableInformationByGivenNumberOfVariable")
	private VariableInformationByGivenNumberOfVariable variableInformationByGivenNumberOfVariable;
	@Resource(name = "campaignIntervalRoundCostInterval")
	private CampaignIntervalRoundCostInterval campaignIntervalRoundCostInterval;

	@Autowired
	private ClientValidator clientValidator;
	@Autowired
	private CostIntervalValueGenerator costIntervalValueGenerator;
	
	@RequestMapping(value = "/campaigns*", method = RequestMethod.GET, produces = "application/json")
	public @ResponseBody
	Map fetchAllCampaignsAndPromocodes() {
		Map<String, Object> container = new HashMap();
		container.put("aaData",
				campaignService.fetchAllCampaignsAndPromocodes());
		return container;
	}

	@RequestMapping(value = "/campaigns*", method = RequestMethod.POST, produces = "application/json")
	public @ResponseBody
	Map createNewCampaign(@Valid @RequestBody RequestClientObject campaign) {
		new CampaignValueGenerator().generate(campaign);
		campaign.setId(RandomNumberGenerator.generateRandomUniqueIDAsInt());
		campaign.setPromocodeId(RandomNumberGenerator.generateRandomUniqueIDAsLong());
		campaignService.insertNewCampaignAndPromocode(campaign);
		if(campaign.getFixCosts() != 0.0 || campaign.getNumberOfVariable() != 0){
			CostintervalClientObject costInterval = new CostintervalClientObject();
			costInterval.setId(RandomNumberGenerator.generateRandomUniqueIDAsLong());
			costInterval.setCampaignId(campaign.getId());
			costInterval.setCostEnd(campaign.getCampaignEnd());
			costInterval.setCostStart(campaign.getCampaignStart());
			costInterval.setFixCosts(campaign.getFixCosts());
			costInterval.setNumberOfVariable(campaign.getNumberOfVariable());
			costIntervalValueGenerator.generate(costInterval);
			costIntervalService.insertNewCostInterval(costInterval);
			dailyCostService.insertNewDailyCosts(costInterval);
		}
		return null;
	}
	
	@RequestMapping(value = "/campaigns/{campaignId}", method = RequestMethod.DELETE, produces = "application/json")
	public @ResponseBody
	Map deleteCampaign(@PathVariable Long campaignId) {
		campaignService.deleteCampaignAndPromocode(campaignId);
		costIntervalService.deleteCostIntervalByCampaignId(campaignId);
		dailyCostService.deleteDailyCostsByCampaignId(campaignId);
		return null;
	}
	
	@RequestMapping(value = "/campaigns*", method = RequestMethod.PUT, produces = "application/json")
	public @ResponseBody
//	Map editCampaign(@Valid @RequestBody RequestClientObject campaign, BindingResult result) {
//		if (result.hasErrors()) {
//			return result.getModel();
//		}
	Map editCampaign(@Valid @RequestBody RequestClientObject campaign) {
		campaignService.editCampaignAndPromocode(campaign);
		return null;
	}
	
	  @InitBinder
	    protected void initBinder(WebDataBinder binder) {
		  binder.addValidators(alreadyExistingCampaign);
		  binder.addValidators(analyticsLinkGenerationError);
		  binder.addValidators(campaignStartAfterEnd);
		  binder.addValidators(costInformationOnlyByGivenDates);
		  binder.addValidators(variableInformationByGivenNumberOfVariable);
		  binder.addValidators(campaignIntervalRoundCostInterval);
	  }
}
